-------------------------------------------------------------------------------
---! 内部方法
-------------------------------------------------------------------------------
---! 查找关卡配置
local function find_stage_config(stage)
    local configs = IMPORT_D:query("wingstage")
    if not configs then
        return
    end

    local config = configs[stage or 1]
    if not config then
        return
    end

    return config
end

---! 查找浮石配置
local function find_stone_config(stage, stoneid)
    local stage_config = find_stage_config(stage)
    if not stage_config then
        return
    end

    local stone_config = stage_config[stoneid or 1]
    if not stone_config then
        return
    end

    return stone_config
end

---! 获取可购买次数
local function get_buy_dice(player)
    local common_config = IMPORT_D:query("wingcommon")
    if not common_config then
        return 0
    end

    local buydice = player:query("wingstage", "buydice")
    if not buydice then
        return player:set("wingstage", "buydice", common_config.randomDiceAddMax)
    end

    return buydice
end

---! 扣除购买次数
local function cost_buy_dice(player, num)
    num = num or 1
    local buydice = get_buy_dice(player)
    if buydice >= num then
        return player:set("wingstage", "buydice", buydice - num)
    end
end

---! 获取购买百变骰子的次数
local function get_buy_variety(player)
    return player:query("wingstage", "buyvariety") or 0
end

---! 累加购买百变骰子的次数
local function add_buy_variety(player)
    return player:set("wingstage", "buyvariety", get_buy_variety(player) + 1)
end

local function get_left_variety(player)
    local common_config = IMPORT_D:query("wingcommon")
    if not common_config then
        return 0
    end

    return math.max(0, common_config.varietyDiceBuyMax - get_buy_variety(player))
end

---! 获取当前浮石位置
local function get_stage_stoneid(player, stage)
    local stoneids = player:query("wingstage", stage, "stoneids")
    if not stoneids or #stoneids <= 0 then
        return 1
    end

    local stoneid = stoneids[#stoneids]
    return stoneid % 1000
end

---! 获取当前最大关卡
local function get_max_stage(player)
    local configs = IMPORT_D:query("wingstage")
    if not configs then
        return 0
    end

    local maxstage = 0
    for stage, _ in ipairs(configs) do
        ---! 获取上次通关时间
        local passtime = player:query("wingstage", stage, "passtime")
        if not passtime then
            break
        end
        maxstage = stage
    end
    return maxstage
end

---!
local function get_total_dewreward(player)
    local configs = IMPORT_D:query("wingstage")
    if not configs then
        return 0
    end

    local dewreward = 0
    for stage, config in ipairs(configs) do
        ---! 判断当前关口未通关
        if not player:query("wingstage", stage, "passtime") then
            break
        end

        ---! 累加统计结算奖励
        dewreward = dewreward + (config.dewreward or 0)
    end

    local common_config = IMPORT_D:query("wingcommon")
    if common_config then
        ---! 累加基础结算奖励
        dewreward = dewreward + (common_config.dewBaseAdd or 0)
    end

    return dewreward
end

---!
local function get_maxdew_interval(player)
    local common_config = IMPORT_D:query("wingcommon")
    if not common_config then
        return 0
    end

    return common_config.dewAddMax
end

---!
local function is_wingstage_opened(player)
    local settletime = player:query("wingstage", "settletime")
    if not settletime then
        return false
    end
    return true
end

-------------------------------------------------------------------------------
---! 对外接口
-------------------------------------------------------------------------------
WINGSTAGE_D = {}

---! 初始副本信息
function WINGSTAGE_D:init_wingstage_info(player)
    ---! 初始翅膀副本信息
    player:set("wingstage", { settletime = os.time(), })

    ---! 设置随机骰子数量
    local common_config = IMPORT_D:query("wingcommon")
    if common_config then
        player:change_currency(GamePropIds.kGamePropIdsRandomDice, common_config.dailyRandomDiceNum)
    end
end

---! 获取副本信息
function WINGSTAGE_D:send_wingstage_data(player, stage)
    ---! 获取当前关口记录
    local stage_map = player:query("wingstage", stage) or {}

    ---! 发送当前过关记录
    local result = {}
    result.stoneids = stage_map.stoneids or {}
    player:send_packet("MSGS2CWingStageData", result)

    ---! 获取上次临时数据
    local temp = stage_map.temp
    if temp then
        ---! 复查浮石配置
        local stone = find_stone_config(stage, temp.stoneid)
        if not stone then
            ---! 数据异常，清理临时数据
            player:delete("wingstage", stage, "temp")
            return
        end

        ---! 通知继续过关
        local result = {}
        result.error = 0
        result.dice = temp.dice
        result.step = temp.step
        result.stoneid = stone.id
        player:send_packet("MSGS2CWingStageDice", result)
    end
end

---! 使用骰子
function WINGSTAGE_D:use_dice(player, stage, step)
    if step < 0 and step > 6 then
        ---! 参数错误
        local result = {}
        result.error = 1
        player:send_packet("MSGS2CWingStageDice", result)
        return
    end

    if not is_wingstage_opened(player) then
        ---! 功能未开启
        local result = {}
        result.error = 2
        player:send_packet("MSGS2CWingStageDice", result)
        return
    end

    local stage_config = find_stage_config(stage)
    if not stage_config then
        ---! 关口不存在
        local result = {}
        result.error = 3
        player:send_packet("MSGS2CWingStageDice", result)
        return
    end

    local last_stage = stage - 1
    if last_stage > 0 and not player:query("wingstage", last_stage, "passtime") then
        ---! 关口未开启
        local result = {}
        result.error = 4
        player:send_packet("MSGS2CWingStageDice", result)
        return
    end

    local temp = player:query("wingstage", stage, "temp")
    if temp then
        ---! 存在上次临时数据
        local result = {}
        result.error = 5
        player:send_packet("MSGS2CWingStageDice", result)
        return
    end

    ---! 获取当前玩家位置
    local stoneid = get_stage_stoneid(player, stage)

    ---! 获取当前浮石配置
    local stone_config = stage_config[stoneid]
    if stoneid > 0 and not stone_config then
        ---! 浮石配置不存在
        local result = {}
        result.error = 6
        player:send_packet("MSGS2CWingStageDice", result)
        return
    end

    if step == 0 then
        ---! 随机骰子
        local leftdice = player:get_currency(GamePropIds.kGamePropIdsRandomDice)
        if leftdice < 1 then
            local result = {}
            result.error = 7
            player:send_packet("MSGS2CWingStageDice", result)
            return
        end

        ---! 随机生成骰子数字
        local next_step = math.random(1, 6)

        ---! 获取下一浮石配置
        local next_stone = stage_config[stoneid + next_step - 1]
        if not next_stone then
            ---! 获取最后一个浮石配置
            next_stone = stage_config[#stage_config]
        end

        ---! 记录当前临时数据
        temp = player:set("wingstage", stage, "temp", { stoneid = next_stone.stoneid, step = next_step, dice = GamePropIds.kGamePropIdsRandomDice, })
    elseif step >= 1 and step <= 6 then
        ---! 百变骰子
        local leftdice = player:get_currency(GamePropIds.kGamePropIdsAssignDice)
        if leftdice < 1 then
            local result = {}
            result.error = 8
            player:send_packet("MSGS2CWingStageDice", result)
            return
        end

        ---! 消耗一个百变骰子
        player:cost_currency(GamePropIds.kGamePropIdsAssignDice, 1)
        ITEM_D:send_currency_info(player)

        ---! 获取指定骰子数字
        local next_step = step

        ---! 获取下一浮石配置
        local next_stone = stage_config[stoneid + next_step - 1]
        if not next_stone then
            ---! 获取最后一个浮石配置
            next_stone = stage_config[#stage_config]
        end

        ---! 记录当前临时数据
        temp = player:set("wingstage", stage, "temp", { stoneid = next_stone.stoneid, step = next_step, dice = GamePropIds.kGamePropIdsAssignDice, })
    end

    ---! 复查浮石配置
    local stone = find_stone_config(stage, temp.stoneid)
    if not stone then
        ---! 数据异常，清理临时数据
        player:delete("wingstage", stage, "temp")
        return
    end

    ---! 通知客户端
    local result = {}
    result.error = 0
    result.dice = temp.dice
    result.step = temp.step
    result.stoneid = stone.id
    player:send_packet("MSGS2CWingStageDice", result)
end

---! 增加骰子
function WINGSTAGE_D:add_dice(player, dicetype)
    local common_config = IMPORT_D:query("wingcommon")
    if not common_config then
        local result = {}
        result.error = 1
        player:send_packet("MSGS2CWingStageDiceAdd", result)
        return
    end

    if dicetype == 0 then
        local buydice = cost_buy_dice(player)
        if not buydice then
            local result = {}
            result.error = 2
            player:send_packet("MSGS2CWingStageDiceAdd", result)
            return
        end

        ---! 给予随机骰子
        player:add_currency(GamePropIds.kGamePropIdsRandomDice, common_config.randomDiceAdd)
    elseif dicetype == 1 then
        local buynum = get_buy_variety(player)
        if buynum >= common_config.varietyDiceBuyMax then
            local result = {}
            result.error = 3
            player:send_packet("MSGS2CWingStageDiceAdd", result)
            return
        end

        local count = math.floor(common_config.varietyDiceBuyNum * (common_config.varietyDiceBuyMul ^ buynum))
        if player:get_currency(GamePropIds.kGamePropIdsDiamondsIcon) < count then
            local result = {}
            result.error = 4
            player:send_packet("MSGS2CWingStageDiceAdd", result)
            return
        end

        ---! 扣除所需费用
        player:cost_currency(GamePropIds.kGamePropIdsDiamondsIcon, count)

        ---! 累加购买次数
        add_buy_variety(player)

        ---! 给予随机骰子
        player:add_currency(GamePropIds.kGamePropIdsAssignDice, 1)
    end

    ---! 刷新相关数据
    ITEM_D:send_currency_info(player)
    WINGSTAGE_D:send_stage_settle(player)

    ---! 通知客户端结果
    local result = {}
    result.error = 0
    result.type = dicetype
    player:send_packet("MSGS2CWingStageDiceAdd", result)
end

---! 通过关卡
function WINGSTAGE_D:pass_stage(player, stage, succ, isdouble)
    local stage_config = find_stage_config(stage)
    if not stage_config then
        local result = {}
        result.error = 1
        player:send_packet("MSGS2CWingStagePass", result)
        return
    end

    local last_stage = stage - 1
    if last_stage > 0 and not player:query("wingstage", last_stage, "passtime") then
        local result = {}
        result.error = 2
        player:send_packet("MSGS2CWingStagePass", result)
        return
    end

    local temp = player:query("wingstage", stage, "temp")
    if not temp then
        local result = {}
        result.error = 3
        player:send_packet("MSGS2CWingStagePass", result)
        return
    end

    ---! 清理临时浮石记录
    player:delete("wingstage", stage, "temp")

    ---! 查找相关浮石配置
    local stone_config = stage_config[temp.stoneid]
    if not stone_config then
        local result = {}
        result.error = 4
        player:send_packet("MSGS2CWingStagePass", result)
        return
    end

    if temp.dice == GamePropIds.kGamePropIdsRandomDice then
        ---! 获取随机骰子
        local leftdice = player:get_currency(GamePropIds.kGamePropIdsRandomDice)
        if leftdice < 1 then
            local result = {}
            result.error = 5
            player:send_packet("MSGS2CWingStagePass", result)
            return
        end

        ---! 消耗随机骰子
        player:cost_currency(GamePropIds.kGamePropIdsRandomDice, 1)
    end

    ---! 获取最后一个浮石
    local final_stone = stage_config[#stage_config]
    if stone_config ~= final_stone then
        ---! 记录当前途径的浮石
        local stoneids = player:query("wingstage", stage, "stoneids")
        if not stoneids then
            stoneids = player:set("wingstage", stage, "stoneids", {})
        end
        table.insert(stoneids, stone_config.id)
    else
        ---! 通关清理浮石数据
        player:delete("wingstage", stage, "stoneids")

        ---! 记录关卡通关时间
        player:set("wingstage", stage, "passtime", os.time())
    end

    local prop = {}
    if stone_config.rewardid > 0 then
        local propId, propCount = stone_config.rewardid, stone_config.rewardnum
        if succ == 0 then
            ---! 挑战失败
            propCount = propCount * (stone_config.rewarddiscount * 10000) / 10000
        end

        if isdouble ~= 0 then
            propCount = propCount * 2
        end

        if propCount > 0 then
            ---! 发送关卡奖励
            player:add_currency(propId, propCount)

            ---! 记录奖励信息
            prop.propId = propId
            prop.propCount = INVENTORY_D:get_currency_show_count(player, propId, propCount)
        end
    end

    ---! 通知通关成功
    local result = {}
    result.error = 0
    result.prop = prop
    result.isDouble = isdouble
    player:send_packet("MSGS2CWingStagePass", result)
    ITEM_D:send_currency_info(player)

    ---! 通知刷新数据
    WINGSTAGE_D:send_wingstage_data(player, stage)
end

---! 发送结算信息
function WINGSTAGE_D:send_stage_settle(player)
    local settletime = player:query("wingstage", "settletime")
    if not settletime then
        ---! 当前功能未开启
        local result = {}
        result.error = 1
        player:send_packet("MSGS2CWingStageSettle", result)
        return
    end

    ---! 获取仙露池水
    local dewtotal = player:query("wingstage", "dewtotal") or 0

    ---! 获取当前时间
    local nowtime = os.time()

    ---! 获取每秒仙露
    local dewreward = get_total_dewreward(player)

    ---! 更新结算时间
    player:set("wingstage", "settletime", nowtime)

    ---! 更新仙露池水
    dewtotal = player:set("wingstage", "dewtotal", math.min(dewtotal + dewreward * (nowtime - settletime), dewreward * get_maxdew_interval(player)))

    ---! 生成货币信息
    local prop = {}
    prop.propId = GamePropIds.kGamePropIdsDewIcon
    prop.propCount = INVENTORY_D:get_currency_show_count(player, GamePropIds.kGamePropIdsDewIcon, dewtotal)

    ---! 通知客户端
    local result = {}
    result.error = 0
    result.prop = prop
    result.buyDice = get_buy_dice(player)
    result.buyVariety = get_left_variety(player)
    result.maxStage = get_max_stage(player)
    player:send_packet("MSGS2CWingStageSettle", result)
end

---! 提取结算奖励
function WINGSTAGE_D:withdraw_stage_settle(player, deposit, isdouble)
    local settletime = player:query("wingstage", "settletime")
    if not settletime then
        ---! 当前功能未开启
        local result = {}
        result.error = 1
        player:send_packet("MSGS2CWingStageWithdraw", result)
        return
    end

    if type(deposit) ~= "table" or deposit.propId ~= GamePropIds.kGamePropIdsDewIcon then
        local result = {}
        result.error = 2
        player:send_packet("MSGS2CWingStageWithdraw", result)
        return
    end

    if deposit.propCount < 1 then
        local result = {}
        result.error = 3
        player:send_packet("MSGS2CWingStageWithdraw", result)
        return
    end

    ---! 获取仙露池水
    local dewtotal = player:query("wingstage", "dewtotal") or 0
    if deposit.propCount > dewtotal then
        local result = {}
        result.error = 4
        player:send_packet("MSGS2CWingStageWithdraw", result)
        return
    end

    ---! 更新仙露池水
    player:set("wingstage", "dewtotal", dewtotal - deposit.propCount)

    ---! 获取仙露奖励
    local dewreward = deposit.propCount
    if isdouble ~= 0 then
        dewreward = dewreward * 2
    end

    ---! 发送仙露奖励
    player:add_currency(GamePropIds.kGamePropIdsDewIcon, dewreward)
    ITEM_D:send_currency_info(player)

    ---! 生成货币信息
    local prop = {}
    prop.propId = GamePropIds.kGamePropIdsDewIcon
    prop.propCount = INVENTORY_D:get_currency_show_count(player, GamePropIds.kGamePropIdsDewIcon, dewreward)

    ---! 通知客户端
    local result = {}
    result.error = 0
    result.prop = prop
    result.isDouble = isdouble
    player:send_packet("MSGS2CWingStageWithdraw", result)

    ---! 更新结算信息
    WINGSTAGE_D:send_stage_settle(player)
end
